package com.scau.jansing.thread.first.queue;

import com.scau.jansing.thread.first.LiftOff;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.concurrent.*;

/**
 * 使用BlockingQueue来代替同步数组操作，比如存取互斥
 *
 * 主线程往队列放元素,如果满了则阻塞；另一个线程从队列中取元素，如果为空则阻塞
 * Created by jansing on 2015/12/23.
 */
public class TestBlockingQueues {

    static void getKey(){
        try {
            new BufferedReader(new InputStreamReader(System.in)).readLine();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    static void getKey(String message){
        System.out.println(message);
        getKey();
    }

    static void test(String msg, BlockingQueue<LiftOff> queue){
        System.out.println(msg);
        LiftOffRunner runner = new LiftOffRunner(queue);
        Thread t = new Thread(runner);
        t.start();
        for(int i=0; i<5; i++){
            runner.add(new LiftOff(5));
        }
        getKey("Press 'Enter' (" + msg + ")");
        t.interrupt();
        System.out.println("Finished " + msg + " test");
    }

    public static void main(String[] args) {
        test("LinkedBlockingQueue ", new LinkedBlockingDeque<>());//不限定元素个数
        test("ArrayBlockingQueue ", new ArrayBlockingQueue<>(2));//限定2个元素
        test("SynchronousQueue", new SynchronousQueue<>());//每次put，都会阻塞等待其他线程take。
    }
}


class LiftOffRunner implements Runnable{

    private BlockingQueue<LiftOff> rockets;
    public LiftOffRunner(BlockingQueue<LiftOff> queue){
        this.rockets = queue;
    }

    public void add(LiftOff liftOff){
        try {
            System.out.println(rockets.size());
            rockets.put(liftOff);
            System.out.println("/"+rockets.size());
        } catch (InterruptedException e) {
            System.out.println("Interrupted during put()");
        }
    }

    @Override
    public void run() {
        try {
            while(!Thread.interrupted()) {
                LiftOff liftOff = rockets.take();
                liftOff.run();
            }
        } catch (InterruptedException e) {
            System.out.println("Waking from take()");
        }
        System.out.println("Exiting LiftOffRunner");
    }
}
